package com.tencent.sr.iris.activity.service.activity.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.tencent.sr.iris.activity.common.enums.ActivityTaskStatusEnum;
import com.tencent.sr.iris.activity.common.enums.AwardRecordIssueStatusEnum;
import com.tencent.sr.iris.activity.common.enums.IrisErrorCode;
import com.tencent.sr.iris.activity.common.enums.TaskRecordAwardIssueStatusEnum;
import com.tencent.sr.iris.activity.common.exception.BizCommErrorCode;
import com.tencent.sr.iris.activity.common.util.ShardingIdUtil;
import com.tencent.sr.iris.activity.common.util.TimeUtils;
import com.tencent.sr.iris.activity.dependency.basic.BasicDependency;
import com.tencent.sr.iris.activity.dependency.dto.activity.QueryAwardReceiveListDTO;
import com.tencent.sr.iris.activity.dependency.dto.data.CommissionInfoDTO;
import com.tencent.sr.iris.activity.dependency.qufa.GroupTaskDependency;
import com.tencent.sr.iris.activity.dependency.user.UserCoreDependency;
import com.tencent.sr.iris.activity.domain.event.dto.ActivityTaskDTO;
import com.tencent.sr.iris.activity.domain.event.dto.InviteLimitDTO;
import com.tencent.sr.iris.activity.domain.event.dto.SpecialOldTttResultDTO;
import com.tencent.sr.iris.activity.interfaces.dto.AwardInfoDTO;
import com.tencent.sr.iris.activity.interfaces.enums.ActivityIdEnum;
import com.tencent.sr.iris.activity.interfaces.request.acticity.QuFaCheckHasJoinSpecialPromoteRequest;
import com.tencent.sr.iris.activity.interfaces.request.task.*;
import com.tencent.sr.iris.activity.interfaces.request.task.PersonalPerformanceReq.PersonalPerformanceDto;
import com.tencent.sr.iris.activity.interfaces.response.activity.QueryAwardReceiveListResponse;
import com.tencent.sr.iris.activity.interfaces.response.activity.UserAwardInfoResponse;
import com.tencent.sr.iris.activity.interfaces.response.group.task.*;
import com.tencent.sr.iris.activity.repository.entity.TIrisActivityAwardRecordDO;
import com.tencent.sr.iris.activity.repository.entity.TIrisActivityTaskDO;
import com.tencent.sr.iris.activity.repository.entity.TIrisUserTaskRecordDO;
import com.tencent.sr.iris.activity.repository.mapper.TIrisUserTaskRecordMapper;
import com.tencent.sr.iris.activity.repository.mapper.example.TIrisUserTaskRecordExample;
import com.tencent.sr.iris.activity.repository.singlemapper.TIrisActivityTaskMapper;
import com.tencent.sr.iris.activity.repository.singlemapper.example.TIrisActivityTaskExample;
import com.tencent.sr.iris.activity.service.activity.ActivityCommonService;
import com.tencent.sr.iris.activity.service.activity.IrisActivityAwardRecordService;
import com.tencent.sr.iris.activity.service.activity.IrisUserActivityRecordService;
import com.tencent.sr.iris.activity.service.activity.IrisUserTaskRecordService;
import com.tencent.sr.iris.activity.service.config.*;
import com.tencent.sr.iris.activity.service.constant.ActivityConfigConstants;
import com.tencent.sr.iris.activity.service.constant.ActivityRedisKey;
import com.tencent.sr.iris.activity.service.convert.ActivityQufaConvert;
import com.tencent.sr.iris.activity.service.event.util.ActivityCommonUtilService;
import com.tencent.sr.iris.activity.service.localcache.LocalCacheManager;
import com.tencent.sr.iris.activity.service.util.IdCreateorUtil;
import com.tencent.sr.iris.basic.service.interfaces.dto.TCommonKvConfigDTO;
import com.tencent.sr.iris.basic.service.interfaces.request.TCommonKvConfigBatchQueryRequest;
import com.tencent.sr.iris.user.core.service.interfaces.dto.IrisUserInfoDTO;
import com.tencent.sr.iris.user.core.service.interfaces.enums.LeaderTypeEnum;
import com.tencent.sr.iris.user.core.service.interfaces.enums.StaffFromTypeEnum;
import com.tencent.sr.iris.user.core.service.interfaces.response.activity.SpecialInviteResponse;
import com.tencent.sr.iris.user.core.service.interfaces.response.activity.SupervisorRelationResponse;
import com.tencent.sr.iris.user.core.service.interfaces.response.user.UserInfoQueryResponse;
import com.tencent.sr.rmall.common.exception.retail.TRetailBizException;
import com.tencent.sr.rmall.common.exception.retail.TRetailErrorException;
import com.tencent.sr.rmall.common.response.PaginationResponse;
import com.tencent.sr.rmall.material.interfaces.enums.EYesNo;
import com.tencent.sr.rmall.springbootstarter.redis.RedisClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.skywalking.apm.toolkit.trace.TraceContext;
import org.springframework.data.util.Pair;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ActivityCommonServiceImpl implements ActivityCommonService {

    @Resource
    private GroupTaskDependency groupTaskDependency;

    @Resource
    private UserCoreDependency userCoreDependency;

    @Resource
    private IdCreateorUtil idCreateorUtil;

    @Resource
    private TIrisActivityTaskMapper activityTaskMapper;

    @Resource
    private SceneConfig sceneConfig;

    @Resource
    private RedisClient redisClient;

    @Resource
    private TaskIssueSwitchConfig taskIssueSwitchConfig;

    @Resource
    private ResponseMockConfig responseMockConfig;

    @Resource
    public ActivityConfig activityConfig;

    @Resource
    private LocalCacheSwitchConfig localCacheSwitchConfig;

    @Resource
    private ActivityCommonUtilService activityCommonUtilService;

    @Resource
    private ActivityQufaConvert activityQufaConvert;

    @Resource
    private BasicDependency basicDependency;

    @Resource
    private IrisUserTaskRecordService userTaskRecordService;

    @Resource
    private InviteGiftTempConfig inviteGiftTempConfig;

    @Resource
    private IrisActivityAwardRecordService awardRecordService;

    @Resource
    private TIrisUserTaskRecordMapper userTaskRecordMapper;

    @Resource
    private IrisUserActivityRecordService activityRecordService;

    //生成发奖入参返回结果为true
    private static final String BUILD_AWARD_REQUEST_TRUE_RESULT = "true";

    @Override
    public UserAwardInfoResponse getAwardInfo(UserAwardInfoRequest request) {
        TIrisActivityTaskExample example = new TIrisActivityTaskExample();
        example.createCriteria()
                .andPropertyEqualTo(TIrisActivityTaskExample.ACTIVITY_ID, request.getActivityType())
                .andPropertyEqualTo(TIrisActivityTaskExample.BIZ_ID, request.getTaskType())
                .andPropertyEqualTo(TIrisActivityTaskExample.STATUS, ActivityTaskStatusEnum.NORMAL.getCode());
        List<TIrisActivityTaskDO> activityTaskDOS = activityTaskMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(activityTaskDOS)) {
            throw new TRetailBizException(BizCommErrorCode.GROUP_TASK_NOT_EXIST);
        }
        TIrisActivityTaskDO irisActivityTaskDO = activityTaskDOS.get(0);
        return UserAwardInfoResponse.convert(getAwardInfoByMarket(irisActivityTaskDO.getAwardInfo()));
    }

    @Override
    public AwardInfoDTO getAwardInfoByMarket(String info) {
        AwardInfoDTO awardInfo = getAwardInfo(info);
        AwardInfoRequest request = new AwardInfoRequest();
        request.setOpenAwardPoolId(awardInfo.getAwardId());
        request.setTransactionFlag(awardInfo.getTransactionFlag());

        QuFaAwardInfoRes quFaAwardInfoRes = groupTaskDependency.getAwardInfo(request,
                sceneConfig.getSceneInfoByScene(awardInfo.getTransactionFlag()));
        if (Objects.nonNull(quFaAwardInfoRes) && CollectionUtils.isNotEmpty(quFaAwardInfoRes.getPosition())) {
            QuFaPositionInfo quFaPositionInfo = quFaAwardInfoRes.getPosition().get(0);
            awardInfo.setValue(Integer.valueOf(quFaPositionInfo.getPrice()));
            awardInfo.setType(quFaPositionInfo.getPoolAwardType());
        }
        return awardInfo;
    }

    @Override
    public AwardInfoDTO getAwardInfoCacheByMarket(String info) {
        AwardInfoDTO awardInfo = getAwardInfo(info);
        String awardId = awardInfo.getAwardId();
        String transactionFlag = awardInfo.getTransactionFlag();

        String key = String.format(ActivityRedisKey.TASK_AWARD_CACHE_KEY, awardId, transactionFlag);
        String cache = redisClient.get(key);
        if (StrUtil.isNotBlank(cache)) {
            return JSON.parseObject(cache, AwardInfoDTO.class);
        }

        awardInfo = getAwardInfoByMarket(info);
        // 随机失效时间
        int expire = new Random().nextInt(3600 - 600) + 600;
        redisClient.setex(key, JSON.toJSONString(awardInfo), expire);

        return awardInfo;
    }

    /**
     * 根据info来解析权益信息。若后续需要切换到营销中台，则取info中获取权益id来调用营销中台来切换底层实现
     *
     * @param info
     * @return
     */
    @Override
    public AwardInfoDTO getAwardInfo(String info) {
        if (StringUtils.isEmpty(info)) {
            return new AwardInfoDTO();
        }
        AwardInfoDTO awardInfoDTO = JSON.parseObject(info, AwardInfoDTO.class);
        return awardInfoDTO;
    }

    @Override
    public CommissionInfoDTO queryCommissionAndSelfBuyGMVInfo(String uid, String startTime, String endTime) {
        CommissionInfoDTO mockDTO = responseMockConfig.getMockCommission(uid);
        if (mockDTO != null) {
            log.info("queryCommissionAndSelfBuyGMVInfo命中mock数据白名单，直接返回mock数据"
                    + "，uid:{}，mockDTO:{}", uid, JSON.toJSONString(mockDTO));
            return mockDTO;
        }
        CommissionInfoDTO commissionInfoDTO = queryCommissionInfo(uid, startTime, endTime);
        Integer gmv = querySelfBuyGMVInfo(uid, startTime, endTime);
        commissionInfoDTO.setGmv(gmv);
        return commissionInfoDTO;
    }

    @Override
    public CommissionInfoDTO queryInviteTaskTarget(String uid, String startTime, String endTime, boolean firstOrder) {
        CommissionInfoDTO commissionInfoDTO = queryCommissionAndSelfBuyGMVInfo(uid, startTime, endTime);
        if (firstOrder && commissionInfoDTO.getFirstOrderInfo() == null) {
            FirstOrderInfoRes firstOrderInfoRes = firstOrderInfo(uid, startTime, endTime);
            commissionInfoDTO.setFirstOrderInfo(firstOrderInfoRes);
        }
        return commissionInfoDTO;
    }

    @Override
    public FirstOrderInfoRes firstOrderInfo(String uid, String startTime, String endTime) {
        log.info("firstOrderInfo uid:{},startTime:{},endTime:{}", uid, startTime, endTime);
        //查询首单信息
        Integer gmv = 0;
        FirstOrderInfoReq req = new FirstOrderInfoReq();
        req.setUid(uid);

        req.setTimeStart(DateUtil.beginOfDay(DateUtil.parse(startTime)).getTime());
        req.setTimeEnd(DateUtil.endOfDay(DateUtil.parse(endTime)).getTime());
        FirstOrderInfoRes response = groupTaskDependency.firstOrderInfo(req);
        log.info("firstOrderInfo uid:{},startTime:{},endTime:{}, response:{}", uid, startTime, endTime,
                JSON.toJSONString(response));
        return response;
    }

    @Override
    public Integer querySelfBuyGMVInfo(String uid, String startTime, String endTime) {
        log.info("querySelfBuyGMVInfo uid:{},startTime:{},endTime:{}", uid, startTime, endTime);
        //查询gmv
        Integer gmv = 0;
        QuerySelfBuyGMVReq req = new QuerySelfBuyGMVReq();
        req.setUids(Arrays.asList(uid));
        req.setSalesDateBegin(startTime);
        req.setSalesDateEnd(endTime);
        PaginationResponse<QuerySelfBuyGMVResponse> response = groupTaskDependency
                .queryUserSelfBuyGMV(req);
        log.info("querySelfBuyGMVInfo uid:{},startTime:{},endTime:{}, response:{}", uid, startTime, endTime,
                JSON.toJSONString(response));
        if (Objects.nonNull(response) && !CollectionUtils.isEmpty(response.getDataList())) {
            List<QuerySelfBuyGMVResponse> dataList = response.getDataList();
            for (int i = 0; i < dataList.size(); i++) {
                QuerySelfBuyGMVResponse item = dataList.get(i);
                if (StringUtils.isNotBlank(item.getSalesOrderType())
                        && "自购".equals(item.getSalesOrderType())
                        && Objects.nonNull(item.getLeaderSalesAmt())) {
                    gmv = item.getLeaderSalesAmt();
                }
            }
        }
        return gmv;
    }

    @Override
    public CommissionInfoDTO queryCommissionInfo(String uid, String startTime, String endTime) {
        CommissionInfoDTO mockDTO = responseMockConfig.getMockCommission(uid);
        if (mockDTO != null) {
            log.info("queryCommissionInfo命中mock数据白名单，直接返回mock数据，uid:{}，mockDTO:{}", uid, JSON.toJSONString(mockDTO));
            return mockDTO;
        }
        Long commission = 0L;
        Long actualCommission = 0L;
        Long waitCommissionAmt = 0L;
        Long rewardIncomeAmt = 0L;
        Long actualSalesRewardIncomeAmtAll = 0L;
        Long salesAmt = 0L;
        Long waitCommissionGmv = 0L;
        Integer shareTime = 0;
        Integer shareUvTo29 = 0;
        Integer shareUvToEndOfMonth = 0;
        //查询佣金
        PersonalPerformanceReq req = new PersonalPerformanceReq();
        PersonalPerformanceDto personalPerformanceDto = PersonalPerformanceDto.builder().uid(uid)
                .salesDateBegin(startTime).salesDateEnd(endTime).build();
        req.setData(personalPerformanceDto);
        req.setPageNo(1);
        req.setPageSize(1);

        PaginationResponse<QuFaPerformancePersonalRes> resPaginationResponse = groupTaskDependency
                .personalPerformanceList(req);
        List<QuFaPerformancePersonalRes> dataList = resPaginationResponse.getDataList();
        if (CollectionUtils.isNotEmpty(dataList)) {
            QuFaPerformancePersonalRes quFaPerformancePersonalRes = dataList.get(0);
            commission = Optional.ofNullable(quFaPerformancePersonalRes.getSalesIncomeAmtAll()).orElse(0L);
            actualCommission = Optional.ofNullable(quFaPerformancePersonalRes.getActualSalesIncomeAmtAll()).orElse(0L);
            rewardIncomeAmt = Optional.ofNullable(quFaPerformancePersonalRes.getRewardIncomeAmt()).orElse(0L);
            actualSalesRewardIncomeAmtAll = Optional.ofNullable(quFaPerformancePersonalRes.getActualSalesRewardIncomeAmtAll()).orElse(0L);
            waitCommissionAmt = Optional.ofNullable(quFaPerformancePersonalRes.getWaitCommissionAmt()).orElse(0L);
            salesAmt = Optional.ofNullable(quFaPerformancePersonalRes.getSalesAmt()).orElse(0L);
            waitCommissionGmv = Optional.ofNullable(quFaPerformancePersonalRes.getWaitCommissionGmv()).orElse(0L);
        }

        //查询有效分享数
        UserShareRequest userShareRequest = new UserShareRequest();
        userShareRequest.setUids(Arrays.asList(uid));
        Date parse = null;
        try {
            parse = new SimpleDateFormat("yyyy-MM-dd").parse(startTime);
            String yyyyMMdd = new SimpleDateFormat("yyyyMMdd").format(parse);
            userShareRequest.setShareVisitTimeStart(yyyyMMdd);
        } catch (Exception e) {
            log.error("queryCommissionInfo startTime format error :{}", startTime);
        }
        log.info("queryCommissionInfo.queryUsersShareVisit request:{}", JSON.toJSONString(userShareRequest));
        List<QuFaUserShareRes> quFaUserShareRes = groupTaskDependency.queryUsersShareVisit(userShareRequest);
        log.info("queryCommissionInfo.queryUsersShareVisit response:{}", JSON.toJSONString(quFaUserShareRes));
        if (CollectionUtils.isNotEmpty(quFaUserShareRes)) {
            QuFaUserShareRes data = quFaUserShareRes.stream()
                    .filter(item -> item.getShareVisitTime().equals(startTime)).findFirst().get();
            if (Objects.nonNull(data)) {
                shareUvTo29 = data.getShareUvTo29();
                shareUvToEndOfMonth = data.getShareUvToEndOfMonth();
            }
        }

        //因8,9月份分享数调整补发，mock分享数
        if ((shareUvTo29 == 0 || shareUvToEndOfMonth == 0)
                && responseMockConfig.needMock(parse)) {
            if (shareUvTo29 == 0) {
                shareUvTo29 = responseMockConfig.getMockVisitCount();
            }
            if (shareUvToEndOfMonth == 0) {
                shareUvToEndOfMonth = responseMockConfig.getMockVisitCount();
            }
        }

        return CommissionInfoDTO.builder()
                .estimateCommission(commission.intValue())
                .commission(actualCommission.intValue())
                .gmv(salesAmt.intValue())
                .waitCommissionAmt(waitCommissionAmt.intValue())
                .sharedTimes(shareTime).shareUvTo29(shareUvTo29)
                .shareUvToEndOfMonth(shareUvToEndOfMonth)
                .waitCommissionGmv(waitCommissionGmv.intValue())
                .actualSalesRewardIncomeAmtAll(actualSalesRewardIncomeAmtAll.intValue())
                .rewardIncomeAmt(rewardIncomeAmt.intValue()).build();
    }

    @Override
    public TIrisActivityAwardRecordDO sendAwardForSupervisor(TIrisUserTaskRecordDO userTaskRecordDO,
            ActivityTaskDTO task) {
        //权益发放幂等id
        String outTradeNo = userTaskRecordDO.getBizId();
        //构建发放流水记录
        TIrisActivityAwardRecordDO awardRecordDO = buildAwardRecordDO(userTaskRecordDO, task, userTaskRecordDO.getPid(),
                outTradeNo);
        RewardSendRequest rewardSendRequest = null;
        QuFaAwardSendRes quFaAwardSendRes = null;
        try {
            //已有发奖记录
            TIrisActivityAwardRecordDO awardRecord = checkAwardSent(userTaskRecordDO, awardRecordDO);
            if (awardRecord != null) {
                return awardRecord;
            }
            //判断发奖开关是否打开
            Boolean taskSwitch = taskIssueSwitchConfig.getTaskSwitch(task.getBizId());
            if (Boolean.FALSE.equals(taskSwitch)) {
                userTaskRecordDO.setAwardIssueStatus(TaskRecordAwardIssueStatusEnum.ISSUE_FAILED.getCode());
                awardRecordDO.setIssueStatus(AwardRecordIssueStatusEnum.ISSUE_FAILED.getCode());
                awardRecordDO.setIssueResult("任务发奖开关关闭，停止发奖");
                return awardRecordDO;
            }
            //校验上级是否虚拟上级
            SupervisorRelationResponse relationResponse = userCoreDependency
                    .queryUserSupervisor(userTaskRecordDO.getUid() + "");
            if (Objects.isNull(relationResponse)) {
                //上级不存在则直接权益发放失败
                userTaskRecordDO.setAwardIssueStatus(TaskRecordAwardIssueStatusEnum.ISSUE_UNABLE.getCode());
                awardRecordDO.setIssueStatus(AwardRecordIssueStatusEnum.ISSUE_UNABLE.getCode());
                awardRecordDO.setIssueResult("上级不存在");
                return awardRecordDO;
            }
            StaffFromTypeEnum parentType = relationResponse.getParentType();
            //上级用户类型为空
            if (Objects.isNull(parentType)) {
                userTaskRecordDO.setAwardIssueStatus(TaskRecordAwardIssueStatusEnum.ISSUE_UNABLE.getCode());
                awardRecordDO.setIssueStatus(AwardRecordIssueStatusEnum.ISSUE_UNABLE.getCode());
                awardRecordDO.setIssueResult("上级类型不是外部团长，类型未知，上级uid：" + relationResponse.getParentUid());
                return awardRecordDO;
            }
            //上级用户类型不是外部团长
            if (relationResponse.isVirParentUid() || !StaffFromTypeEnum.isOuterSign(parentType.getCode())) {
                userTaskRecordDO.setAwardIssueStatus(TaskRecordAwardIssueStatusEnum.ISSUE_UNABLE.getCode());
                awardRecordDO.setIssueStatus(AwardRecordIssueStatusEnum.ISSUE_UNABLE.getCode());
                awardRecordDO.setIssueResult(
                        "上级类型不是外部团长，类型为：" + parentType.getCode() + "，上级uid：" + relationResponse.getParentUid());
                return awardRecordDO;
            }
            //构建权益发放请求体
            Pair<String, RewardSendRequest> pairResult = buildRewardSendRequest(userTaskRecordDO,
                    task, outTradeNo, userTaskRecordDO.getPid());
            //请求体参数不完整则记录下来
            if (!BUILD_AWARD_REQUEST_TRUE_RESULT.equals(pairResult.getFirst())) {
                userTaskRecordDO.setAwardIssueStatus(TaskRecordAwardIssueStatusEnum.ISSUE_FAILED.getCode());
                awardRecordDO.setIssueStatus(AwardRecordIssueStatusEnum.ISSUE_FAILED.getCode());
                awardRecordDO.setIssueResult(
                        "上级uid：" + relationResponse.getParentUid() + "发放权益参数错误:" + JSON.toJSONString(pairResult));
                return awardRecordDO;
            }
            rewardSendRequest = pairResult.getSecond();
            String recordInfoKey = ActivityRedisKey.getAwardTaskRecordInfoKey(rewardSendRequest.getUid(), userTaskRecordDO.getBizId());
            redisClient.setex(recordInfoKey, JSON.toJSONString(userTaskRecordDO), 60 * 60 * 24 * 30);

            //调用区发权益发放接口
            quFaAwardSendRes = groupTaskDependency.awardSend(rewardSendRequest,
                    sceneConfig.getSceneInfoByScene(rewardSendRequest.getTransactionFlag()));
            log.info("sendAwardForSupervisor request:{},response:{}", JSON.toJSONString(rewardSendRequest),
                    JSON.toJSONString(quFaAwardSendRes));
            if (Objects.nonNull(quFaAwardSendRes)) {
                //权益发放成功则记录状态成功
                userTaskRecordDO.setAwardIssueStatus(TaskRecordAwardIssueStatusEnum.ISSUE_SUCCEED.getCode());
                awardRecordDO.setIssueStatus(AwardRecordIssueStatusEnum.ISSUE_SUCCEED.getCode());
                String s = JSON.toJSONString(quFaAwardSendRes);
                awardRecordDO.setIssueResult(StringUtils.substring(s, 0, 500));
            }
        } catch (TRetailBizException e) {
            //区发权益发放接口异常则记录
            log.error("qufa sendAwardForSupervisor error,request:{},response:{}", JSON.toJSONString(rewardSendRequest),
                    JSON.toJSONString(quFaAwardSendRes), e);
            handleIssueUnableError(userTaskRecordDO, awardRecordDO, e);
        }  catch (Exception e) {
            //区发权益发放接口异常则记录
            log.error("sendAwardForSupervisor error,request:{},response:{}", JSON.toJSONString(rewardSendRequest),
                    JSON.toJSONString(quFaAwardSendRes), e);
            userTaskRecordDO.setAwardIssueStatus(TaskRecordAwardIssueStatusEnum.ISSUE_FAILED.getCode());
            awardRecordDO.setIssueStatus(AwardRecordIssueStatusEnum.ISSUE_FAILED.getCode());
            String s = Optional.ofNullable(e.getMessage()).orElse("");
            awardRecordDO.setIssueResult(StringUtils.substring(s, 0, 500));
        }
        return awardRecordDO;
    }

    /**
     * 处理不可发奖错误
     * @param userTaskRecordDO
     * @param awardRecordDO
     * @param e
     */
    private void handleIssueUnableError(TIrisUserTaskRecordDO userTaskRecordDO, TIrisActivityAwardRecordDO awardRecordDO, TRetailBizException e) {
        if (e.getErrorCode() != null
                && IrisErrorCode.REQUEST_QUFA_FAIL_UN_RETRY.getCode().equals(e.getErrorCode().getCode())) {
            userTaskRecordDO.setAwardIssueStatus(TaskRecordAwardIssueStatusEnum.ISSUE_UNABLE.getCode());
            awardRecordDO.setIssueStatus(AwardRecordIssueStatusEnum.ISSUE_UNABLE.getCode());
        } else {
            awardRecordDO.setIssueStatus(AwardRecordIssueStatusEnum.ISSUE_FAILED.getCode());
            userTaskRecordDO.setAwardIssueStatus(TaskRecordAwardIssueStatusEnum.ISSUE_FAILED.getCode());
        }
        String s = Optional.ofNullable(e.getMessage()).orElse("");
        awardRecordDO.setIssueResult(StringUtils.substring(s, 0, 500));
    }

    /**
     *
     * @param userTaskRecordDO
     * @param awardRecordDO
     * @return
     */
    private TIrisActivityAwardRecordDO checkAwardSent(TIrisUserTaskRecordDO userTaskRecordDO, TIrisActivityAwardRecordDO awardRecordDO) {
        String uid = userTaskRecordDO.getUid();
        String activityId = userTaskRecordDO.getActivityId();
        String taskId = userTaskRecordDO.getTaskId();
        String taskRecordId = userTaskRecordDO.getBizId();
        if (activityConfig.isValidateAwardSent()) {
            TIrisActivityAwardRecordDO awardRecord = awardRecordService.queryAwardRecord(uid, activityId, taskId, taskRecordId);
            if (awardRecord != null) {
                log.warn("查询到已有发奖记录：{}, 关联的任务记录：{}", JSON.toJSONString(awardRecord), JSON.toJSONString(userTaskRecordDO));
                userTaskRecordDO.setAwardIssueStatus(TaskRecordAwardIssueStatusEnum.ISSUE_SUCCEED.getCode());
                awardRecord.setIssueStatus(AwardRecordIssueStatusEnum.ISSUE_UNABLE.getCode());
                awardRecord.setIssueResult("存在发奖成功或无需发奖的发奖记录，不再调用发奖接口，直接返回成功");
                return awardRecord;
            }
        }

        //如果已经发过奖，不再调用发奖接口
        if (userTaskRecordDO.getAwardIssueStatus() != null
                && TaskRecordAwardIssueStatusEnum.ISSUE_SUCCEED.getCode() == userTaskRecordDO.getAwardIssueStatus()) {
            userTaskRecordDO.setAwardIssueStatus(TaskRecordAwardIssueStatusEnum.ISSUE_SUCCEED.getCode());
            awardRecordDO.setIssueStatus(AwardRecordIssueStatusEnum.ISSUE_SUCCEED.getCode());
            awardRecordDO.setIssueResult("任务已经发过奖，不在调用发奖接口，直接返回成功");
            return awardRecordDO;
        }
        return null;
    }


    @Override
    public TIrisActivityAwardRecordDO sendAward(TIrisUserTaskRecordDO userTaskRecordDO, ActivityTaskDTO task) {
        String outTradeNo = userTaskRecordDO.getBizId();
        TIrisActivityAwardRecordDO awardRecordDO = buildAwardRecordDO(userTaskRecordDO, task, userTaskRecordDO.getUid(),
                outTradeNo);
        //已有发奖记录
        TIrisActivityAwardRecordDO awardRecord = checkAwardSent(userTaskRecordDO, awardRecordDO);
        if (awardRecord != null) {
            return awardRecord;
        }
        //发放权益
        Pair<String, RewardSendRequest> pairResult = buildRewardSendRequest(userTaskRecordDO, task,
                outTradeNo, userTaskRecordDO.getUid());

        //判断发奖开关是否打开
        Boolean taskSwitch = taskIssueSwitchConfig.getTaskSwitch(task.getBizId());
        if (Boolean.FALSE.equals(taskSwitch)) {
            userTaskRecordDO.setAwardIssueStatus(TaskRecordAwardIssueStatusEnum.ISSUE_FAILED.getCode());
            awardRecordDO.setIssueStatus(AwardRecordIssueStatusEnum.ISSUE_FAILED.getCode());
            awardRecordDO.setIssueResult("任务发奖开关关闭，停止发奖");
            return awardRecordDO;
        }

        //请求体参数不完整则记录下来
        if (!BUILD_AWARD_REQUEST_TRUE_RESULT.equals(pairResult.getFirst())) {
            userTaskRecordDO.setAwardIssueStatus(TaskRecordAwardIssueStatusEnum.ISSUE_FAILED.getCode());
            awardRecordDO.setIssueStatus(AwardRecordIssueStatusEnum.ISSUE_FAILED.getCode());
            awardRecordDO.setIssueResult("发放权益参数错误:" + JSON.toJSONString(pairResult));
            return awardRecordDO;
        }
        RewardSendRequest rewardSendRequest = pairResult.getSecond();
        QuFaAwardSendRes quFaAwardSendRes = null;
        try {
            String recordInfoKey = ActivityRedisKey.getAwardTaskRecordInfoKey(rewardSendRequest.getUid(), userTaskRecordDO.getBizId());
            redisClient.setex(recordInfoKey, JSON.toJSONString(userTaskRecordDO),  60 * 60 * 24 * 30);

            quFaAwardSendRes = groupTaskDependency.awardSend(rewardSendRequest,
                    sceneConfig.getSceneInfoByScene(rewardSendRequest.getTransactionFlag()));
            log.info("sendAward request:{},response:{}", JSON.toJSONString(rewardSendRequest),
                    JSON.toJSONString(quFaAwardSendRes));
            if (Objects.nonNull(quFaAwardSendRes)) {
                userTaskRecordDO.setAwardIssueStatus(TaskRecordAwardIssueStatusEnum.ISSUE_SUCCEED.getCode());
                awardRecordDO.setIssueStatus(AwardRecordIssueStatusEnum.ISSUE_SUCCEED.getCode());
                String s = JSON.toJSONString(quFaAwardSendRes);
                awardRecordDO.setIssueResult(StringUtils.substring(s, 0, 500));
            }
        } catch (TRetailBizException e) {
            //区发权益发放接口异常则记录
            log.error("qufa awardSend error,request:{},response:{}", JSON.toJSONString(rewardSendRequest),
                    JSON.toJSONString(quFaAwardSendRes), e);
            handleIssueUnableError(userTaskRecordDO, awardRecordDO, e);
        } catch (Exception e) {
            //区发权益发放接口异常则记录
            log.error("qufa awardSend error,request:{},response:{}", JSON.toJSONString(rewardSendRequest),
                    JSON.toJSONString(quFaAwardSendRes), e);
            userTaskRecordDO.setAwardIssueStatus(TaskRecordAwardIssueStatusEnum.ISSUE_FAILED.getCode());
            awardRecordDO.setIssueStatus(AwardRecordIssueStatusEnum.ISSUE_FAILED.getCode());
            String s = Optional.ofNullable(e.getMessage()).orElse("");
            awardRecordDO.setIssueResult(StringUtils.substring(s, 0, 500));
        }
        return awardRecordDO;
    }

    @Override
    public TIrisUserTaskRecordDO queryAwardTaskRecordInfo(String uid, String taskBizId) {
        String recordInfoKey = ActivityRedisKey.getAwardTaskRecordInfoKey(uid, taskBizId);
        String s = redisClient.get(recordInfoKey);
        if (StrUtil.isNotBlank(s)) {
            return JSON.parseObject(s, TIrisUserTaskRecordDO.class);
        }

        TIrisUserTaskRecordExample example = new TIrisUserTaskRecordExample();
        example.createCriteria().andPropertyEqualTo(TIrisUserTaskRecordExample.UID, uid)
                .andPropertyEqualTo(TIrisUserTaskRecordExample.BIZ_ID, taskBizId)
                .andPropertyEqualTo(TIrisUserTaskRecordExample.STATUS, EYesNo.NO.getValue())
                .andPropertyEqualTo(TIrisUserTaskRecordExample.SHARDING_ID, ShardingIdUtil.sharding(uid));
        List<TIrisUserTaskRecordDO> taskRecords = userTaskRecordMapper.limitSelectByExample(example, 0, 1);
        if (CollectionUtil.isNotEmpty(taskRecords)) {
            return taskRecords.get(0);
        }
        return null;
    }

    private Pair<String/*参数是否完整*/, RewardSendRequest/*参数*/> buildRewardSendRequest(
            TIrisUserTaskRecordDO userTaskRecordDO,
            ActivityTaskDTO task, String outTradeNo, String awardUid) {
        RewardSendRequest rewardSendRequest = new RewardSendRequest();
        if (Objects.isNull(task) || Objects.isNull(userTaskRecordDO) || StringUtils.isBlank(outTradeNo)
                || StringUtils.isBlank(awardUid)) {
            log.error("buildRewardSendRequest 参数缺失，task:{},userTaskRecordDO:{},outTradeNo:{},awardUid:{}"
                    , JSON.toJSONString(task), JSON.toJSONString(userTaskRecordDO), outTradeNo, awardUid);
            return Pair.of("buildRewardSendRequest 参数缺失", rewardSendRequest);
        }
        //权益发送人uid
        rewardSendRequest.setUid(awardUid);
        //权益发送幂等id
        rewardSendRequest.setOutTradeNo(outTradeNo);
        //查询权益发送人unionId、openId
        Pair<String, String> unionOpenIdPair = userCoreDependency.queryUnionOpenIdByUid(awardUid);
        //注册有礼查询不到openId的话通过调用区发接口获取他们的openId和appId，兼容在线招募的用户没有登陆过小程序的情况
        if (unionOpenIdPair == null && activityConfig.getRegistGiftActivityId().equals(task.getActivityId())) {
            String unionId = userCoreDependency.queryUnionIdByUid(awardUid);
            String openid = null;
            if (StringUtils.isNoneBlank(unionId)) {
                //查询区发接口获取openId
                QueryOpenIdRequest queryOpenIdRequest = new QueryOpenIdRequest();
                queryOpenIdRequest.setUnionid(unionId);
                QueryOpenIdResponse queryOpenIdResponse = groupTaskDependency.queryOpenId(queryOpenIdRequest);
                log.info("query qufa openId uid:{} unionID:{} response:{}", awardUid,
                        unionId, JSON.toJSONString(queryOpenIdResponse));
                if (Objects.nonNull(queryOpenIdResponse)) {
                    openid = queryOpenIdResponse.getOpenid();
                    rewardSendRequest.setWechatAppId(queryOpenIdResponse.getAppid());
                }
            }
            if (!StringUtils.isEmpty(unionId) && !StringUtils.isEmpty(openid)) {
                unionOpenIdPair = Pair.of(unionId, openid);
            }
        }
        if (unionOpenIdPair == null) {
            log.info("发奖uid:" + awardUid + "没查到unionOpenId");
            return Pair.of("发奖uid:" + awardUid + "没查到unionOpenId", rewardSendRequest);
        }
        //获取unionId
        if (StringUtils.isEmpty(unionOpenIdPair.getFirst())) {
            log.error("发奖uid:" + awardUid + ",没查到unionId");
            return Pair.of("发奖uid:" + awardUid + ",没查到unionId", rewardSendRequest);
        }
        rewardSendRequest.setUnionId(unionOpenIdPair.getFirst());
        //获取openId
        if (StringUtils.isEmpty(unionOpenIdPair.getSecond())) {
            log.error("发奖uid:" + awardUid + ",没查到openId");
            return Pair.of("发奖uid:" + awardUid + ",没查到openId", rewardSendRequest);
        }
        rewardSendRequest.setOpenid(unionOpenIdPair.getSecond());
        //权益信息
        Pair<String, RewardSendRequest> result = handleAwardInfo(awardUid, userTaskRecordDO, task, rewardSendRequest);
        if (result != null) {
            return result;
        }

        //查询等级
        UserInfoQueryResponse userInfoQueryResponse = userCoreDependency.queryUserInfo(awardUid, false);
        if (Objects.isNull(userInfoQueryResponse)) {
            log.error("发奖uid:" + awardUid + ",没查到等级");
            return Pair.of("发奖uid:" + awardUid + ",没查到等级", rewardSendRequest);
        }
        IrisUserInfoDTO userInfoDTO = userInfoQueryResponse.getUserInfoDTO();
        String levelId = userInfoDTO.getLevelId();
        rewardSendRequest.setSignUpLevel(levelId);
        //查询参与时间
        String startTimeStr = TimeUtils
                .parse(userTaskRecordDO.getCurrentTaskStartTime(), TimeUtils.YYYY_MM_DD_HH_MM_SS);
        rewardSendRequest.setSignUpTime(startTimeStr);
        //任务名称
        rewardSendRequest.setTaskName(task.getName());
        //任务id
        rewardSendRequest.setTaskId(String.valueOf(task.getBizId()));
        //下级贡献开始时间
        rewardSendRequest.setAwardSourceUserStartTime(startTimeStr);
        //即给上级贡献的下级uid
        String uid = userTaskRecordDO.getUid();
        rewardSendRequest.setAwardSourceUid(uid);
        //参与开始时间
        rewardSendRequest.setValidPeriodStart(startTimeStr);
        //参与结束时间
        rewardSendRequest.setValidPeriodEnd(TimeUtils.parse(new Date(), TimeUtils.YYYY_MM_DD_HH_MM_SS));

        //设置归结时间
        if (Objects.equals(userTaskRecordDO.getActivityId(), ActivityIdEnum.SPECIAL_INVITE_REWARD.getCode())) {
            //被邀请成为特邀的月份
            SpecialInviteResponse specialInviteResponse = activityCommonUtilService.querySpecialInviteCache(uid);
            Long expensesTimestamp = Optional.ofNullable(specialInviteResponse)
                    .map(SpecialInviteResponse::getTimeStamp).orElse(null);
            rewardSendRequest.setExpensesTimestamp(expensesTimestamp);
        } else {
            rewardSendRequest.setExpensesTimestamp(userTaskRecordDO.getCurrentTaskStartTime().getTime());
        }

        return Pair.of(BUILD_AWARD_REQUEST_TRUE_RESULT, rewardSendRequest);
    }

    /**
     * 处理发奖信息
     * @param awardUid
     * @param task
     * @param rewardSendRequest
     * @return
     */
    private Pair<String, RewardSendRequest> handleAwardInfo(String awardUid, TIrisUserTaskRecordDO userTaskRecordDO,
                                                            ActivityTaskDTO task, RewardSendRequest rewardSendRequest) {
        String awardInfo = task.getAwardInfo();
        if (StringUtils.isBlank(awardInfo)) {
            log.error("发奖uid:" + awardUid + ",没查到权益信息");
            return Pair.of("发奖uid:" + awardUid + ",没查到权益信息", rewardSendRequest);
        }

        String uid = userTaskRecordDO.getUid();
        Date currentTaskStartTime = userTaskRecordDO.getCurrentTaskStartTime();
        String extInfo = userTaskRecordDO.getExtInfo();

        JSONObject jsonObject = Optional.ofNullable(JSONObject.parseObject(awardInfo)).orElseGet(JSONObject::new);
        String transactionFlag = jsonObject.getString("transactionFlag");
        boolean firstOrderAward = activityCommonUtilService.firstOrderAward(uid, currentTaskStartTime);
        if (Objects.equals(task.getActivityId(), ActivityIdEnum.INVITE_GIFT.getCode()) && firstOrderAward) {
            JSONObject newAward = Optional.ofNullable(jsonObject.getJSONObject("newAward")).orElseGet(JSONObject::new);
            String awardId = newAward.getString("awardId");
            Integer value = newAward.getInteger("value");
            if (StringUtils.isBlank(awardId) || StringUtils.isBlank(transactionFlag) || value == null) {
                String msg = "发奖uid:" + awardUid + ",没查到awardId，awardValue或者transactionFlag";
                log.error(msg);
                return Pair.of(msg, rewardSendRequest);
            }
            //发奖份数
            JSONObject firstOrder = activityCommonUtilService.parseExtInfoField(extInfo, "firstOrder");
            if (firstOrder == null) {
                String msg = "发奖uid:" + awardUid + ",邀请有礼发奖未查到首单信息";
                log.error(msg);
                return Pair.of(msg, rewardSendRequest);
            }
            Integer couponPrice = Optional.ofNullable(firstOrder.getInteger("couponPrice")).orElse(0);
            Integer paymentAmount = Optional.ofNullable(firstOrder.getInteger("paymentAmount")).orElse(0);
            int payValue = paymentAmount - couponPrice;
            if (payValue <= 0) {
                String msg = "发奖uid:" + awardUid + ",邀请有礼发奖首单实付金额减去新人券面额小于等于0";
                log.error(msg);
                return Pair.of(msg, rewardSendRequest);
            }
            int actualSendValue = payValue <= value ? payValue : value;
            rewardSendRequest.setAwardNum(actualSendValue);
            userTaskRecordDO.setSendAward(actualSendValue);
            //奖池id
            rewardSendRequest.setOpenAwardPoolId(Integer.parseInt(awardId));
            //场景值
            rewardSendRequest.setTransactionFlag(transactionFlag);
        } else {
            String awardId = jsonObject.getString("awardId");
            Integer value = Optional.ofNullable(jsonObject.getInteger("value")).orElse(0);
            if (StringUtils.isBlank(awardId) || StringUtils.isBlank(transactionFlag)) {
                log.error("发奖uid:" + awardUid + ",没查到awardId或者transactionFlag");
                return Pair.of("发奖uid:" + awardUid + ",没查到awardId或者transactionFlag", rewardSendRequest);
            }
            //奖池id
            rewardSendRequest.setOpenAwardPoolId(Integer.parseInt(awardId));
            //场景值
            rewardSendRequest.setTransactionFlag(transactionFlag);
            userTaskRecordDO.setSendAward(value);
        }
        return null;
    }

    @Override
    public TIrisActivityAwardRecordDO buildAwardRecordDO(TIrisUserTaskRecordDO userTaskRecordDO,
            ActivityTaskDTO task, String awardUid, String outTradeNo) {
        TIrisActivityAwardRecordDO awardRecordDO = new TIrisActivityAwardRecordDO();
        awardRecordDO.setBizId(idCreateorUtil.genId());
        awardRecordDO.setUid(userTaskRecordDO.getUid());
        awardRecordDO.setActivityId(userTaskRecordDO.getActivityId());
        awardRecordDO.setTaskId(userTaskRecordDO.getTaskId());
        awardRecordDO.setAwardType(task.getAwardType());
        awardRecordDO.setAwardInfo(task.getAwardInfo());
        awardRecordDO.setAwardUid(awardUid);
        JSONObject extInfo = new JSONObject();
        extInfo.put("taskRecordBizId", userTaskRecordDO.getBizId());
        extInfo.put("outTradeNo", outTradeNo);
        extInfo.put("traceId", TraceContext.traceId());
        awardRecordDO.setExtInfo(extInfo.toJSONString());
        awardRecordDO.setTaskRecordId(userTaskRecordDO.getBizId());
        return awardRecordDO;
    }

    /**
     * 查询成功见习会员时间
     *
     * @param uid
     * @return
     */
    @Override
    public Long queryTraineeTime(String uid) {
        Long traineeTime = responseMockConfig.getMockTraineeTime(uid);
        if (traineeTime != null) {
            log.info("queryTraineeTime 命中mock数据白名单，直接返回mock数据，uid:{}，traineeTime:{}", uid, traineeTime);
            return traineeTime;
        }
        if (localCacheSwitchConfig.isUserTraineeTimeON()) {
            try {
                traineeTime = LocalCacheManager.LOCALCACHE_USER_TRAINEETIME
                        .get(uid, () -> Optional.ofNullable(userCoreDependency.queryTraineeTime(uid))).orElse(null);
            } catch (ExecutionException e) {
                log.error("获取见习会员时间异常", e);
            }
        } else {
            traineeTime = userCoreDependency.queryTraineeTime(uid);
        }
        return traineeTime;
    }

    /**
     * 查询邀请有礼策略切换时间
     *
     * @param uid
     * @return
     */
    @Override
    public Long queryInviteChangeTime(String uid) {
        Long changeTime = inviteGiftTempConfig.getInviteGiftChangeTime().getTime();
        if (StringUtils.isNotBlank(uid)) {
            Long changeTimeMock = responseMockConfig.getInviteChangeTime(uid);
            if (changeTimeMock != null) {
                log.info("queryInviteChangeTime 命中mock数据白名单，直接返回mock数据，uid:{}，traineeTime:{}", uid, changeTime);
                changeTime = changeTimeMock;
            }
        }
        return changeTime;
    }

    /**
     * 查询邀请有礼上限策略切换时间
     *
     * @param uid
     * @return
     */
    @Override
    public Long queryInviteUpperLimitChangeTime(String uid) {
        Long changeTime = inviteGiftTempConfig.getInviteGiftUpperLimitChangeTime().getTime();
        if (StringUtils.isNotBlank(uid)) {
            Long changeTimeMock = responseMockConfig.getInviteUpperLimitChangeTime(uid);
            if (changeTimeMock != null) {
                log.info("queryInviteUpperLimitChangeTime 命中mock数据白名单，"
                        + "直接返回mock数据，uid:{}，traineeTime:{}", uid, changeTime);
                changeTime = changeTimeMock;
            }
        }
        return changeTime;
    }

    @Override
    public SpecialOldTttResultDTO handleSpecialOldTttCache(String uid, long eventTime) {
        try {
            if (localCacheSwitchConfig.isQuerySpecialOldTttON()) {
                Optional<SpecialOldTttResultDTO> optional = LocalCacheManager.SPECIAL_OLD_TTT_RESULT.get(uid,
                        () -> Optional.ofNullable(handleSpecialOldTtt(uid, eventTime)));
                if (!optional.isPresent()) {
                    throw new TRetailErrorException("查询老团推团失败");
                }
                return optional.get();
            } else {
                return handleSpecialOldTtt(uid, eventTime);
            }
        } catch (ExecutionException e) {
            throw new TRetailErrorException("查询老团推团缓存失败", e);
        }
    }

    @Override
    public SpecialOldTttResultDTO handleSpecialOldTtt(String uid, long eventTime) {
        DateTime strictStandardStartTime = DateUtil.parse(activityConfig.getStrictStandardStartTimeByUid(uid));
        long standardStartTimeStamp = strictStandardStartTime.getTime();

        SpecialInviteResponse specialInviteResponse = activityCommonUtilService.querySpecialInviteCache(uid);

        Long specialInviteTimeStamp = specialInviteResponse.getTimeStamp();
        if (Objects.equals(LeaderTypeEnum.SPECIAL_LEADER.getCode(), specialInviteResponse.getTag())
                && specialInviteTimeStamp != null && specialInviteTimeStamp < standardStartTimeStamp) {
            //5月1日0点前，已成为特邀的，需走营销中台接口判断特邀老TTT是否已结束
            QuFaCheckHasJoinSpecialPromoteRequest request = new QuFaCheckHasJoinSpecialPromoteRequest().setUid(uid);
            QuFaCheckHasJoinSpecialPromoteRes res = responseMockConfig.getSpecialOldTttMock(uid);
            if (res == null) {
                res = groupTaskDependency.checkHasJoinSpecialPromote(request);
                log.info("营销老团推团返回信息：{}", JSON.toJSONString(res));
            }
            DateTime promoteEnd = DateUtil.parse(res.getPromoteEnd());
            if (Objects.equals(res.getHasJoin(), (int) EYesNo.YES.getValue())) {
                log.info("老团推团未结束，无法参与月月领活动，成为特邀时间：{}，老团推团返回信息：{}",
                        DateUtil.formatDateTime(DateUtil.date(specialInviteTimeStamp)), JSON.toJSONString(res));
                return SpecialOldTttResultDTO.builder().satisfy(false).oldTttEndTime(null).build();
            }
            //未曾参与老团推团
            if (promoteEnd == null) {
                return SpecialOldTttResultDTO.builder().satisfy(true).oldTttEndTime(null).build();
            }

            //老团推团已结束
            if (promoteEnd.getTime() <= System.currentTimeMillis()) {
                Date plusDay = null;
                //结束时间在5月1日0点后，任务时间老TTT结束第二天~任务结束时间
                if (promoteEnd.getTime() >= standardStartTimeStamp) {
                    plusDay = DateUtil.beginOfDay(DateUtil.offsetDay(promoteEnd, 1));
                    if (plusDay.getTime() > eventTime) {
                        log.info("任务处理：老团推团结束第二天时间大于事件时间，不处理，eventTime:{},oldTttEndTime:{}", DateUtil.date(eventTime),
                                plusDay);
                        throw new TRetailBizException("老团推团结束第二天时间不在任务时间范围内，不处理");
                    }
                }
                return SpecialOldTttResultDTO.builder().satisfy(true).oldTttEndTime(plusDay).build();
            }

            log.info("老团推团未结束，无法参与月月领活动，成为特邀时间：{}，老团推团返回信息：{}",
                    DateUtil.formatDateTime(DateUtil.date(specialInviteTimeStamp)), JSON.toJSONString(res));
            return SpecialOldTttResultDTO.builder().satisfy(false).oldTttEndTime(null).build();
        }

        return SpecialOldTttResultDTO.builder().satisfy(true).oldTttEndTime(null).build();
    }


    @Override
    public List<QueryAwardReceiveListResponse> queryAwardReceiveList(List<String> outTradeNoList) {
        List<QueryAwardReceiveListDTO> awardRecords = groupTaskDependency.queryAwardReceiveList(outTradeNoList);
        return awardRecords.stream().map(activityQufaConvert::buildResponseFromDTO)
                .collect(Collectors.toList());
    }

    @Override
    public Integer getLevelInviteLimit(String level, String uid) {
        if (StringUtils.isBlank(level)) {
            return null;
        }

        if (activityConfig.getTestUidWhiteList().contains(uid)) {
            return responseMockConfig.getLevelInviteLimitMock().get(level);
        }
        return activityConfig.getLevelInviteLimitConfig().get(level);
    }

    @Override
    public InviteLimitDTO queryInviteLimit(String uid, Long becomeTraineeTime) {
        if (StringUtils.isBlank(uid) || Objects.isNull(becomeTraineeTime)) {
            return InviteLimitDTO.builder().satisfy(false).isError(true).desc("获取邀请上限参数不全").build();
        }
        String monthStr = DateUtil.format(new Date(becomeTraineeTime), "yyyyMM");
        InviteLimitDTO result = queryUserInviteLimit(uid, monthStr);
        if (result == null) {
            return InviteLimitDTO.builder().satisfy(false).isError(true).desc("获取邀请上限错误").build();
        }
        try {
            //查询该用户在becomeTraineeTime所在当月已经邀请了多少,名额占用了多少
            Pair<Integer, Integer> pair = userTaskRecordService
                    .queryInviteLimitSeqByPid(uid, new Date(becomeTraineeTime));
            if (Objects.isNull(pair)) {
                return InviteLimitDTO.builder().satisfy(false).isError(true).desc("获取已邀请人数错误").build();
            }
            if (pair.getSecond() < result.getInviteLimit()) {
                result.setSatisfy(true);
            }
            result.setInviteDevoteNum(pair.getSecond());
            int inviteSeq = pair.getFirst() + 1;
            result.setInviteSeq(inviteSeq);
        } catch (Exception e) {
            log.error("获取uid:{}已邀请人数错误：", uid, e);
            return InviteLimitDTO.builder().satisfy(false).isError(true).desc("获取已邀请人数错误").build();
        }
        return result;
    }

    @Override
    public InviteLimitDTO queryUserInviteLimit(String uid, String monthStr) {
        if (StrUtil.isBlank(uid)) {
            return null;
        }

        Date now = new Date();
        InviteLimitDTO result = new InviteLimitDTO();
        result.setUid(uid);
        if (StringUtils.isEmpty(monthStr)) {
            monthStr = DateUtil.format(now, "yyyyMM");
        }
        String parentKey = String.format(ActivityConfigConstants.MONTH_LIMIT_CONFIG_MONTH_KEY, monthStr);
        String key = String.format(ActivityConfigConstants.MONTH_LIMIT_CONFIG_UID_KEY, uid);
        TCommonKvConfigBatchQueryRequest queryRequest = new TCommonKvConfigBatchQueryRequest();
        queryRequest.setParentKey(parentKey);
        queryRequest.setConfigKeyList(Arrays.asList(key));
        try {
            List<TCommonKvConfigDTO> configList = basicDependency.batchQueryCommonKVNoCache(queryRequest);
            //判断是否指定了该用户邀请上限
            if (CollectionUtils.isNotEmpty(configList)) {
                String configValue = configList.get(0).getConfigValue();
                if (StringUtils.isNotBlank(configValue)) {
                    result.setInviteLimit(Integer.parseInt(configValue));
                }
            }
            //没有指定该用户邀请上限，则根据等级获取上限
            if (Objects.isNull(result.getInviteLimit())) {
                //查询是否需要走mock
                Map<String, Integer> levelInviteLimitMock = responseMockConfig.getLevelInviteLimitMock();
                String levelId = activityCommonUtilService.queryUserLevelIdUseCache(uid);
                if (activityConfig.getTestUidWhiteList().contains(uid) && levelInviteLimitMock.containsKey(levelId)) {
                    result.setInviteLimit(levelInviteLimitMock.get(levelId));
                } else {
                    //不走mock则查询七彩石配置,先查询有没有给等级配置月份,没有则走默认等级配置
                    String levelMapKey = new StringBuffer().append(levelId).append("-").append(monthStr).toString();
                    if (Objects.nonNull(activityConfig.getLevelInviteLimitMap())
                            && activityConfig.getLevelInviteLimitMap().containsKey(levelMapKey)){
                        result.setInviteLimit(activityConfig.getLevelInviteLimitMap().get(levelMapKey));
                    } else {
                        result.setInviteLimit(activityConfig.getLevelInviteLimitConfig().get(levelId));
                    }
                }
            }
            if (Objects.isNull(result.getInviteLimit())) {
                return null;
            }
        } catch (Exception e) {
            log.error("获取uid:{}邀请上限错误：", uid, e);
            return null;
        }
        log.info("queryUserInviteLimit uid:{},monthStr:{},result:{}", uid, monthStr, JSON.toJSONString(result));
        return result;
    }

    @Override
    public Map<String, Map<String, Integer>> queryInviteLimitMap(List<String> uidList, List<Date> dateList) {
        if (CollectionUtil.isEmpty(uidList) || CollectionUtil.isEmpty(dateList)) {
            return Collections.emptyMap();
        }

        List<String> dateStrList = dateList.stream()
                .map(i -> DateUtil.format(Optional.ofNullable(i).orElseGet(Date::new), "yyyyMM"))
                .distinct().collect(Collectors.toList());
        Map<String, Map<String, Integer>> res = Maps.newHashMap();
        for (String monthStr : dateStrList) {

            Map<String, String> keyMap = uidList.stream().collect(Collectors.toMap(
                    i -> String.format(ActivityRedisKey.ACTIVITY_INVITE_LIMIT_KEY, monthStr, i),
                    i -> i, (i1, i2) -> i1));
            List<String> keys = Lists.newArrayList(keyMap.keySet());

            Function<List<String>, List<InviteLimitDTO>> queryFunc = keysList -> keysList.stream()
                    .map(i -> queryUserInviteLimit(keyMap.get(i), monthStr)).collect(Collectors.toList());
            Function<InviteLimitDTO, String> keyFunc = i -> String.format(ActivityRedisKey.ACTIVITY_INVITE_LIMIT_KEY, monthStr, i.getUid());
            Function<InviteLimitDTO, String> serializer = i -> JSON.toJSONString(i);
            Function<String, InviteLimitDTO> deserializer = i -> JSON.parseObject(i, InviteLimitDTO.class);

            List<InviteLimitDTO> resList = activityCommonUtilService.batchQueryCache(keys, 1800,
                    queryFunc, keyFunc, serializer, deserializer);

            Map<String, Integer> map = resList.stream().collect(Collectors.toMap(
                    InviteLimitDTO::getUid, InviteLimitDTO::getInviteLimit, (i1, i2) -> i1));
            res.put(monthStr, map);
        }
        return res;
    }

    /**
     * 获取预估收益-通过activityId和taskId缓存(预估收益流水)
     *
     * @param request
     * @return
     */
    @Override
    public UserAwardInfoResponse getAwardInfoByActivityAndTask(UserAwardInfoRequest request) {

        try {
            log.info("getAwardInfoByActivityAndTask开始获取活动的预估收益,request:{}", JSONObject.toJSONString(request));
            String key = String.format(ActivityRedisKey.TASK_AWARD_ACTIVITY_TASK_ESTIMATED_CACHE_KEY,
                    request.getActivityType(), request.getTaskType());
            log.info("getAwardInfoByActivityAndTask开始获取活动的预估收益,得到缓存key值为:{}", key);
            String cache = redisClient.get(key);
            log.info("getAwardInfoByActivityAndTask开始获取活动的预估收益,得到缓存对象:{}", cache);
            if (StrUtil.isNotBlank(cache)) {
                log.info("getAwardInfoByActivityAndTask开始获取活动的预估收益,命中缓存,返回值为:{}", cache);
                return JSON.parseObject(cache, UserAwardInfoResponse.class);
            }
            int expire = new Random().nextInt(3600 - 600) + 600;
            UserAwardInfoResponse response = getAwardInfo(request);
            log.info("getAwardInfoByActivityAndTask开始获取活动的预估收益,未命中缓存请求接口数据,请求参数request为:{},返回值为:{}",
                    JSONObject.toJSONString(request), cache);
            redisClient.setex(key, JSON.toJSONString(response), expire);
            return response;

        } catch (Exception e) {
            log.error("getAwardInfoByActivityAndTask获取活动的预估收益失败,request:{}", JSONObject.toJSONString(request), e);
        }
        return null;
    }

    @Override
    public InviteLimitDTO queryInviteLimitByAward(String uid, Long becomeTraineeTime) {
        if (StringUtils.isBlank(uid) || Objects.isNull(becomeTraineeTime)) {
            return InviteLimitDTO.builder().satisfy(false).isError(true).desc("获取派奖上限参数不全").build();
        }

        Date date = new Date(becomeTraineeTime);
        String monthStr = DateUtil.format(date, "yyyyMM");
        InviteLimitDTO result = queryUserInviteLimit(uid, monthStr);
        if (result == null) {
            return InviteLimitDTO.builder().satisfy(false).isError(true).desc("获取派奖上限错误").build();
        }
        try {
            //查询该用户在becomeTraineeTime所在当月已经发了几次奖
            Integer num;
            if (activityConfig.isCountAwardFromActivityRecord()) {
                num = activityRecordService.queryAwardTotalByPid(uid, date);
            } else {
                num = userTaskRecordService.queryAwardTotalByPid(uid, date);
            }
            if (num < result.getInviteLimit()) {
                result.setSatisfy(true);
            }
            result.setInviteDevoteNum(num);
        } catch (Exception e) {
            log.error("获取uid:{}已派奖人数错误：", uid, e);
            return InviteLimitDTO.builder().satisfy(false).isError(true).desc("获取已派奖人数错误").build();
        }
        return result;
    }
}
